package ch.bfh.medinfo.javafx.dice.implementation;

import java.util.Random;

import ch.bfh.medinfo.javafx.dice.definition.Dice;

/**
 * It is very difficult to realize if a dice is unfair... Watch this one:
 * Every n-th play, the value is biased towards maxValue... But not too strong -- only a little bit.
 * Its effect can be observed after several 100 plays if it is instanciated with winnerPosition=1 meaning that each play will be biased.
 * @author reto
 * 
 */
public class UnFairDice implements Dice {
	private static final Random random;
	private int minValue;
	private int maxValue;
	private int actualValue;
	private int winnerPosition;
	private int actualCount;

	/**
	 * Instanciation of randomization. This is done only once, when the class is
	 * loaded via standard class loader.
	 */
	static {
		random = new Random();
	}

	/**
	 * 
	 * @param minValue
	 * @param maxValue
	 */
	public UnFairDice(int minValue, int maxValue, int winnerPosition) {
		// Verify if values make sense
		if (minValue >= maxValue)
			throw new IllegalArgumentException();
		if (winnerPosition < 0)
			throw new IllegalArgumentException();
		// Assign values
		this.maxValue = maxValue;
		this.minValue = minValue;

		this.winnerPosition = winnerPosition;

		initialize();
	}

	protected void initialize() {
		// Play a first time, in order to initialize acutalValue
		play();
	}

	@Override
	public void play() {
		// Calculate the range between min and max
		int range = Math.abs(this.maxValue - this.minValue);

		// get a random value within the range (careful: random(3) -> 0,1,2 but
		// never 3)
		int randomValueInRange = random.nextInt(range + 1);

		this.actualValue = this.minValue + randomValueInRange;
		
		//The following code guarantees that the winning position has a slight bias versus maxValue
		if (actualCount++ % this.winnerPosition==0)
			
			//In 50% of the cases, the winning position is shifted up towards maxValue
			if(random.nextBoolean())
				this.actualValue = Math.min(actualValue + 1, this.maxValue);
	}

	@Override
	public int getActualValue() {
		return this.actualValue;
	}

	@Override
	public int getMinValue() {
		return this.minValue;
	}

	@Override
	public int getMaxValue() {
		return this.maxValue;
	}

}
